package com.qianyitian.hope2.analyzer.controller;

import com.alibaba.fastjson.JSON;
import com.qianyitian.hope2.analyzer.analyzer.DemarkAnalyzer;
import com.qianyitian.hope2.analyzer.analyzer.EStockAnalyzer;
import com.qianyitian.hope2.analyzer.analyzer.IStockAnalyzer;
import com.qianyitian.hope2.analyzer.analyzer.StockAnalyzerFacotry;
import com.qianyitian.hope2.analyzer.config.Constant;
import com.qianyitian.hope2.analyzer.model.*;
import com.qianyitian.hope2.analyzer.service.*;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@RestController
public class AnalysisController {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    DemarkService demarkService;

    @Autowired
    private StockService stockService;

    @Resource(name = "fileSystemStorageService")
    private IReportStorageService reportService;

    @Autowired
    StockAnalyzerFacotry stockAnalyzerFacotry;

    public AnalysisController() {
    }

    @RequestMapping(value = "/status", method = RequestMethod.GET)
    public String status() {
        return LocalDateTime.now().toString();
    }

    @Async
    @RequestMapping(value = "/startAnalyze", method = RequestMethod.GET)
    @Scheduled(cron = "0 21 20 * * MON,TUE,WED,THU,FRI")
    //每周1-5 19:53:00 执行
    public void startAnalyzeInBackgroud() {
        analyzePortfolio("selection", Constant.TYPE_DAILY);
        for (EStockAnalyzer enumAnalyzer : EStockAnalyzer.values()) {
            if (enumAnalyzer.getType().contains(EStockAnalyzer.WEEKLY)) {
                analyze(enumAnalyzer, Constant.TYPE_WEEKLY);
            }
        }
        for (EStockAnalyzer enumAnalyzer : EStockAnalyzer.values()) {
            if (enumAnalyzer.getType().contains(EStockAnalyzer.DAILY)) {
                analyze(enumAnalyzer, Constant.TYPE_DAILY_LITE, Constant.TYPE_DAILY);
            }
        }
        for (EStockAnalyzer enumAnalyzer : EStockAnalyzer.values()) {
            if (enumAnalyzer.getType().contains(EStockAnalyzer.MONTHLY)) {
                analyze(enumAnalyzer, Constant.TYPE_MONTHLY);
            }
        }
    }

    @Async
    @RequestMapping(value = "/startDemarkAnalyze", method = RequestMethod.GET)
    public void startDemarkAnalyze() {
        analyze(EStockAnalyzer.Demark, Constant.TYPE_DAILY_LITE, Constant.TYPE_DAILY);
        analyze(EStockAnalyzer.Demark, Constant.TYPE_WEEKLY);
        analyze(EStockAnalyzer.Demark, Constant.TYPE_MONTHLY);
    }


    @RequestMapping(value = "/analysis/{analyzerName}/daily", method = RequestMethod.GET)
    @CrossOrigin
    public String analyze(@PathVariable String analyzerName) {
        String filename = analyzerName + "-daily";
        return lazyLoadReport(filename);
    }


    @RequestMapping(value = "/analysis/{analyzerName}/weekly", method = RequestMethod.GET)
    @CrossOrigin
    public String analyzeByWeekly(@PathVariable String analyzerName) {
        String filename = analyzerName + "-weekly";
        return lazyLoadReport(filename);
    }

    @RequestMapping(value = "/analysis/{analyzerName}/monthly", method = RequestMethod.GET)
    @CrossOrigin
    public String analyzeByMonthly(@PathVariable String analyzerName) {
        String filename = analyzerName + "-monthly";
        return lazyLoadReport(filename);
    }

    @RequestMapping(value = "/analysis/intersection-report", method = RequestMethod.GET)
    @CrossOrigin
    public String reportByIntersection(@RequestParam String[] report) {
        if (ArrayUtils.isEmpty(report)) {
            return "";
        }
        return readReportByIntersection(report);
    }

    @RequestMapping(value = "/statistics/increaseRangeStatistics", method = RequestMethod.GET)
    public String increaseRangeStatistics() {
        String filename = "increaseRangeStatistics";
        return reportService.getStatistics(filename);
    }


    private void analyzePortfolio(String portfolio, String kLineType) {
        String report = demarkService.demarkSelectionAllStocks(DemarkAnalyzer.DEFAULT_DAYS2NOW, 22);
        storeAnalysisResult(report, portfolio, kLineType);
    }

    private void analyze(EStockAnalyzer analyzer, String kLineType) {
        analyze(analyzer, kLineType, kLineType);
    }

    private void analyze(EStockAnalyzer analyzerE, String retreivalKLineType, String storageKlineType) {
        IStockAnalyzer analyzer = stockAnalyzerFacotry.getStockAnalyzer(analyzerE);
        SymbolList symbols = null;
        if(analyzerE.name().startsWith("US")){
            symbols = stockService.getSymbols("us");
        }else{
            symbols = stockService.getSymbols(null);
        }
        StockSelecter hs = null;
        if (analyzerE == EStockAnalyzer.Demark) {
            //不用再跑一边demark了，如果是跑Demark，那么跑哪个T，就使用哪个T
            hs = new StockSelecter(symbols.getSymbols(), stockService);
        } else {
            //跑一边demark，如果是跑其他算法，无论跑哪个T, 都使用Daily算 Demark
            hs = new StockSelecterDemarkResult(symbols.getSymbols(), stockService);
        }

        hs.addAnalyzer(analyzer);
        hs.startAnalyze(retreivalKLineType);
        AnalyzeResult result = hs.getAnalyzeResult();
        String report = JSON.toJSONString(result);
        if (report != null) {
            storeAnalysisResult(report, analyzerE, storageKlineType);
        }
    }

    private void storeAnalysisResult(String result, EStockAnalyzer enumAnalyzer, String type) {
        String filename = enumAnalyzer.name() + "-" + type;
        reportService.storeAnalysis(filename, result);
        logger.info("Store report successful " + filename);
    }

    private void storeAnalysisResult(String report, String portfolio, String type) {
        String key = portfolio + type;
        reportService.storeAnalysis(key, report);
        logger.info("Store report successful " + key);
    }

    private String lazyLoadReport(String filename) {
        return reportService.getAnalysis(filename);
    }

    private String readReportByIntersection(String[] reports) {
        List<ResultInfo> initialList = null;

        for (String s : reports) {
            String reportJson = lazyLoadReport(s);
            if (StringUtils.isEmpty(reportJson)) {
                continue;
            }
            AnalyzeResult result = JSON.parseObject(reportJson, AnalyzeResult.class);
            if (initialList == null) {
                initialList = result.getResultList();
            } else {
                logger.error("left size " + initialList.size() + "     right size " + result.getResultList().size());
                initialList.retainAll(result.getResultList());
                logger.error("merged size " + initialList.size());
            }
        }


        AnalyzeResult result = new AnalyzeResult();
        result.setGenerateTime(LocalDateTime.now().toString());
        result.setResultList(initialList);
        return JSON.toJSONString(result);
    }
}
